package com.hup.restTimer.view.setting;

import com.hup.restTimer.model.AppConfig;
import com.hup.restTimer.service.ImageService;
import com.hup.restTimer.service.MainService;
import com.hup.restTimer.view.main.MainWindow;
import com.hup.utils.commons.hardware.MouseUtil;
import com.hup.utils.commons.start.LookThemeUtil;
import com.hup.utils.commons.start.SpringContext;
import com.hup.utils.commons.start.StartupInfo;
import com.hup.utils.swing.ColorUtil;
import com.hup.utils.swing.ComponentUtil;
import com.hup.utils.swing.FrameUtil.Gravity;
import com.hup.utils.swing.ImageUtil;
import com.hup.utils.swing.customView.colorChooser.ColorChooserPanel;
import com.hup.utils.swing.frame.BaseFrame;
import com.hup.utils.swing.frame.SingletonWindowHelper;
import lombok.extern.slf4j.Slf4j;

import java.awt.Color;
import java.awt.Font;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

/**
 * 设置界面
 * .界面修改是即时生效的,无保存/取消按钮
 *
 * @author hugan
 * @date 2022/10/1
 */
@Slf4j
public class SettingFrame extends BaseFrame {

    private final AppConfig config;
    private final MainWindow window;

    private SettingForm form;

    /**
     * 切换显示状态
     *
     * @param show nullable-切换当前状态, notNull-切换到指定状态
     */
    public static void switchShow(Boolean show) {
        SettingFrame settingFrame = SingletonWindowHelper.getWindow(SettingFrame.class);
        if (show == null) show = settingFrame == null;
        if (show) {
            if (settingFrame == null) {
                settingFrame = new SettingFrame(SpringContext.getBean(AppConfig.class));
            }
            settingFrame.setVisible(true);
            settingFrame.toFront();
            settingFrame.window.setVisible(true);
        } else {
            if (settingFrame != null) settingFrame.dispose();
        }
    }

    public SettingFrame(AppConfig config) {
        super(StartupInfo.getApplicationChName());
        this.config = config;
        window = SingletonWindowHelper.getWindow(MainWindow.class);
        //log.info("window={}", window);

        initView();
        initListener();
    }

    private void initView() {
        form = new SettingForm();
        setContentPane(form.root);
        form.cbFont.setModel(config.fontNames);
        form.txtNotSupportPenetration.setVisible(config.notSupportPenetration);

        //自动高度,固定宽度
        pack();
        setSize((int) (450 * LookThemeUtil.getScreenScale()), getHeight());
        setLocationRelativeTo(null);
        setResizable(false);
        handleFrameTop();

        //初始化配置
        form.txtSitTimeMax.setIntValue((int) (config.sitTimeMax / 60000));
        //提醒文本
        form.txtTipsTemplate.setText(config.tipsTemplate);
        form.txtTipsTemplateRest.setText(config.tipsTemplateRest);
        form.cbFont.setSelectedItem(config.tipsFont);
        form.txtFontSize.setIntValue(config.tipsFontSize);
        updateFontColor(new Color(config.tipsColor, true));
        form.cbGravity.setSelectedItem(Gravity.get(config.tipsGravity, Gravity.TOP_CENTER));
        form.txtMargin.setIntValue(config.tipsMargin);
        form.cbTipsOutline.setSelected(config.tipsOutline);
        //休息背景图
        form.cbImageShow.setSelected(config.imageShow);
        form.cbImagePenetration.setSelected(config.imagePenetration);
        form.slImageAlpha.setValue(config.imageAlpha);
        form.txtImagePath.setSelectedFilePath(config.imagePath);
        form.txtImageChangeTime.setIntValue(config.imageChangeTime / 1000);
        form.cbImageRandom.setSelected(config.imageRandom);
        onChangeImageShow();

    }

    private void initListener() {
        //一般设置
        form.txtSitTimeMax.addChangeListener(e -> {
            config.sitTimeMax = form.txtSitTimeMax.getIntValue() * 60000;
            log.info("sitTimeMax={}", config.sitTimeMax);
        });
        form.btnResetSitTime.addActionListener(e -> {
            config.restTimeLastEd = System.currentTimeMillis();
            window.getTipsLabel().updateTimeStr();
        });
        //提醒文本
        form.txtTipsTemplate.addActionListener(e -> applyTipsTemplate());
        form.txtTipsTemplate.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                applyTipsTemplate();
            }
        });
        form.txtTipsTemplateRest.addActionListener(e -> applyTipsTemplateRest());
        form.txtTipsTemplateRest.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                applyTipsTemplateRest();
            }
        });
        form.cbFont.addActionListener(e -> applyFont());
        form.txtFontSize.addChangeListener(e -> applyFont());
        form.txtColor.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() != 1 || (!MouseUtil.isLeftButton(e) && !MouseUtil.isRightButton(e))) return;
                Color res = ColorChooserPanel.showDialog(SettingFrame.this, new Color(config.tipsColor, true));
                if (res == null) return;
                config.tipsColor = res.getRGB();
                updateFontColor(res);
                window.getTipsLabel().setColor(config.tipsColor);
            }
        });
        form.cbGravity.addActionListener(e -> {
            Gravity gravity = form.cbGravity.getSelectedItem();
            assert gravity != null;
            config.tipsGravity = gravity.value;
            window.getTipsLabel().repaint();
        });
        form.txtMargin.addChangeListener(e -> {
            config.tipsMargin = form.txtMargin.getIntValue();
            window.getTipsLabel().repaint();
            log.info("tipsMargin={}", config.tipsMargin);
        });
        form.cbTipsOutline.addActionListener(e -> {
            config.tipsOutline = form.cbTipsOutline.isSelected();
            window.getTipsLabel().updateTimeStr();
        });
        //休息背景图
        form.cbImageShow.addActionListener(e -> {
            config.imageShow = form.cbImageShow.isSelected();
            onChangeImageShow();
            //
            SpringContext.getBean(MainService.class).updateWindowStyle(true);
            handleFrameTop();
        });
        form.cbImagePenetration.addActionListener(e -> {
            config.imagePenetration = form.cbImagePenetration.isSelected();
            SpringContext.getBean(MainService.class).updateWindowStyle(false);
            handleFrameTop();
        });
        form.slImageAlpha.addChangeListener(e -> {
            boolean adjusting = form.slImageAlpha.getValueIsAdjusting();
            if (adjusting) return;
            int alpha = form.slImageAlpha.getValue();
            config.imageAlpha = alpha;
            log.info("imageAlpha={}", alpha);
            BufferedImage image = window.getBackgroundLabel().getIconImage();
            if (image != null) {
                //log.info("刷新alpha.st");
                ImageUtil.updateAlpha(image, alpha);
                window.getBackgroundLabel().repaint();
                //log.info("刷新alpha.ed");//耗时很少,100ms左右
            }
        });
        form.txtImagePath.setChoseListener(chosePath -> {
            config.imagePath = form.txtImagePath.getSelectedFilePath();
            log.info("imagePath={}", config.imagePath);
            ImageService imageService = SpringContext.getBean(ImageService.class);
            imageService.onImagePathUpdated();
            imageService.doTickTask(window);
        });
        form.txtImageChangeTime.addChangeListener(e -> config.imageChangeTime = form.txtImageChangeTime.getIntValue() * 1000);
        form.cbImageRandom.addActionListener(e -> {
            config.imageRandom = form.cbImageRandom.isSelected();
            ImageService imageService = SpringContext.getBean(ImageService.class);
            imageService.onImagePathUpdated();
            imageService.doTickTask(window);
        });
    }

    private void onChangeImageShow() {
        form.cbImagePenetration.setEnabled(config.imageShow);
        form.slImageAlpha.setEnabled(config.imageShow);
        form.txtImagePath.setEnabled(config.imageShow);
        form.txtImageChangeTime.setEnabled(config.imageShow);
        form.cbImageRandom.setEnabled(config.imageShow);
    }

    private void handleFrameTop() {
        //只要显示背景图,就要置顶,因为背景图可能不透明
        setAlwaysOnTop(config.imageShow);
        toFront();
    }

    /**
     * @param color 带透明度的color
     */
    private void updateFontColor(Color color) {
        form.txtColor.setText("  (" + ColorUtil.getIntText(color) + ")  ");
        ComponentUtil.setBackground(form.txtColor, color);
        Color reverse = new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue());//不带透明度的反色
        //Color reverse = ColorUtil.reverse(color);
        form.txtColor.setForeground(reverse);
        log.info("updateFontColor={}", ColorUtil.getIntText(color));
    }

    private void applyTipsTemplate() {
        config.tipsTemplate = form.txtTipsTemplate.getText();
        window.getTipsLabel().updateTimeStr();
        log.info("tipsTemplate={}", config.tipsTemplate);
    }

    private void applyTipsTemplateRest() {
        config.tipsTemplateRest = form.txtTipsTemplateRest.getText();
        window.getTipsLabel().updateTimeStr();
        log.info("applyTipsTemplateRest={}", config.tipsTemplateRest);
    }

    private void applyFont() {
        config.tipsFont = form.cbFont.getSelectedItem();
        config.tipsFontSize = form.txtFontSize.getIntValue();
        log.info("font={}, {}", config.tipsFont, config.tipsFontSize);
        window.getTipsLabel().setFont(new Font(config.tipsFont, Font.BOLD, config.tipsFontSize));
    }

    /**
     * 对于本界面的text控件,如果输入完后,马上关闭窗口
     * .则会先触发text的[focusLost,ChangeListener等]
     * .然后才到达本方法,不用担心config没更新
     */
    @Override
    public void onHidden(boolean dispose) {
        log.info("");
        //要重算
        long cur = System.currentTimeMillis();
        config.isNeedRest = (cur - config.restTimeLastEd) > config.sitTimeMax;
        //
        boolean showTipsWindow = config.isResting || (config.isNeedRest && !config.notTips);
        if (!showTipsWindow) window.setVisible(false);
        config.save();
    }

}
